View Javadoc

1   /*
2    * Copyright (c) 2004-2005, University Health Network.  All rights reserved. Distributed under the BSD 
3    * license (see http://opensource.org/licenses/bsd-license.php).
4    * 
5    * Created on 25-Jan-2005
6    */
7   package ca.uhn.cache.util;
8   
9   import java.util.NoSuchElementException;
10  
11  import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
12  import ca.uhn.cache.util.exception.MutableIteratorException;
13  
14  /***
15   * Default implementation of IMutableIterator.  The default 
16   * close() method does nothing, and should be overridden to perform any 
17   * required cleanup.  
18   * 
19   * Note that this class is NOT thread-safe in the sense of supporting multiple 
20   * iterating clients or competing threads calling add and freeze (although 
21   * different threads may add and iterate concurrently).  It is assumed that one 
22   * thread is iterating.  It is up to the caller to ensure that freeze() is not called 
23   * until after add() has been called as for the last time.     
24   * 
25   * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
26   * @version $Revision: 1.1 $ updated on $Date: 2005/01/26 00:25:50 $ by $Author: bryan_tripp $
27   */
28  public class MutableIterator implements IMutableIterator {
29  
30      private LinkedQueue myQueue;
31      private Object myNext;
32      private MutableIteratorException myException;
33      private boolean myIsFrozen = false;
34      
35      /***
36       * New instance. 
37       */
38      public MutableIterator() {
39          myQueue = new LinkedQueue();
40      }
41  
42      /*** 
43       * @see ca.uhn.cache.IMutableIterator#add(java.lang.Object)
44       */
45      public synchronized void add(Object theObject) {
46          if (myIsFrozen) {
47              throw new IllegalStateException("Can't add to a frozen IMutableIterator");
48          }            
49          
50          try {
51              myQueue.put(theObject);
52          } catch (InterruptedException e) {
53              declareException(e);
54          }        
55      }
56      
57      /***
58       * @see ca.uhn.cache.IMutableIterator#freeze()
59       */
60      public synchronized void freeze() {
61          myIsFrozen = true;            
62          
63          try {
64              myQueue.put(new EndMarker());
65          } catch (InterruptedException e) {
66              declareException(e);
67          }        
68      }    
69      
70      /***
71       * @see java.util.Iterator.hasNext()
72       */
73      public boolean hasNext() throws MutableIteratorException {
74          if (myException != null) {
75              throw myException;
76          }
77          
78          while (myNext == null) {
79              try {
80                  myNext = myQueue.poll(1);
81              } catch (InterruptedException e) {
82                  //we'll just try again
83              }
84          }
85          
86          boolean done = (myNext instanceof EndMarker);
87          if (done) {
88              close();
89          }
90          
91          return !done;
92      }
93  
94      /*** 
95       * @see java.util.Iterator#next()
96       */
97      public Object next() throws MutableIteratorException, NoSuchElementException {
98          if (myException != null) {
99              throw myException;
100         }
101         
102         if (!hasNext()) {
103             throw new NoSuchElementException("No further items are available");
104         } 
105         
106         Object next = myNext;
107         myNext = null;            
108         
109         return next;
110     }
111 
112     /*** 
113      * Does nothing by default.  Override if you need to do more. 
114      *  
115      * @see ca.uhn.cache.IMutableIterator#close()
116      */
117     public void close() {
118     }
119 
120     /***
121      * @see ca.uhn.cache.IMutableIterator#declareException(java.lang.Exception)
122      */
123     public void declareException(Exception theException) {
124         myException = new MutableIteratorException(theException);
125     }
126     
127     /*** 
128      * @see java.util.Iterator#remove()
129      */
130     public void remove() {
131         throw new UnsupportedOperationException(
132                 "Remove has no meaning here as this iterator isn't tied to a specific source");
133     }
134 
135     /***
136      * Marker added to queue on finish().  Could set a finished flag, but this might be 
137      * out of order due to threading.  
138      *  
139      * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
140      * @version $Revision: 1.1 $ updated on $Date: 2005/01/26 00:25:50 $ by $Author: bryan_tripp $
141      */
142     private static class EndMarker {
143     }
144 
145 }